use std::collections::BTreeMap;

use crate::{client::TongLianPayClient, utils};
use anyhow::{Result, bail};

#[derive(Debug)]
pub struct CloseResponse {
    pub trxstatus: String,
    pub errmsg: Option<String>,
}
impl TongLianPayClient {
    async fn close(&self, mut body: BTreeMap<&str, &str>) -> Result<CloseResponse> {
        body.insert("cusid", self.mch_credential.cusid.as_str());
        body.insert("appid", self.mch_credential.appid.as_str());
        body.insert("signtype", self.mch_credential.signtype.as_str());
        let randomstr = utils::generate_none_str(32);
        body.insert("randomstr", randomstr.as_str());
        // 加签
        let plain = utils::btree_map_to_query_string(&body);
        let sign = self.mch_credential.sign(plain.as_str());
        body.insert("sign", &sign);

        let url = format!("{}/apiweb/tranx/close", self.base_url);
        let response = self
            .client
            .post(&url)
            .form(&body)
            .header("Accept", "application/json")
            .send()
            .await?;
        if !response.status().is_success() {
            bail!("支付关闭失败");
        }
        let mut response: BTreeMap<String, String> = response.json().await?;
        if response.get("retcode") != Some(&"SUCCESS".to_string()) {
            bail!(
                response
                    .get("retmsg")
                    .cloned()
                    .unwrap_or_else(|| "支付关闭失败".to_string())
            );
        }
        // 验签
        self.mch_credential.verify_response(&mut response)?;

        // 处理返回结果
        let trxstatus = response
            .get("trxstatus")
            .cloned()
            .unwrap_or_else(|| "未知状态".to_string());
        let errmsg = response.get("errmsg").cloned();

        Ok(CloseResponse { trxstatus, errmsg })
    }
    pub async fn close_by_reqsn(&self, reqsn: &str) -> Result<CloseResponse> {
        let mut body = BTreeMap::new();
        body.insert("oldreqsn", reqsn);
        self.close(body).await
    }
    pub async fn close_by_trxid(&self, trxid: &str) -> Result<CloseResponse> {
        let mut body = BTreeMap::new();
        body.insert("oldtrxid", trxid);
        self.close(body).await
    }
}
